package com.yonginitagmaker.atv;

import java.io.Console;
import java.io.IOException;
import java.nio.charset.Charset;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.yonginitagmaker.R;
import com.yonginitagmaker.common.Constants;
import com.yonginitagmaker.util.Alert;
import com.yonginitagmaker.util.Alert.OnCloseListener;
import com.yonginitagmaker.util.LogUtil;

public class AtvMakingTag extends Activity
{
	private static final String	TAG				= "NFCWriteTag";

	private NfcAdapter			mNfcAdapter;
	private IntentFilter[]		mWriteTagFilters;
	private PendingIntent		mNfcPendingIntent;

	private boolean				mWriteProtect	= false;

	private Context				mContext;

	private TextView			mTxtTitle		= null;
	private TextView			mTxtContents	= null;
	private Button				mBtnOK			= null;
	// private Button mBtnClose = null;

	private String				mShopNo			= "";

	private final Charset		CHART_SET		= Charset.forName("US-ASCII");

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.atv_making_tag);

		mContext = getApplicationContext();

		findView();
		init();
		configureListener();
		initNFC();
	}

	private void findView()
	{
		mTxtTitle = (TextView) findViewById(R.id.txtTopTitle);
		mTxtContents = (TextView) findViewById(R.id.txtContents);
		mBtnOK = (Button) findViewById(R.id.btnOK);
		// mBtnClose = (Button) findViewById(R.id.btnClose);
	}

	private void init()
	{
		if(getIntent() != null && getIntent().hasExtra(Constants.BUNDLE_KEY_SHOP_NO))
		{
			mShopNo = getIntent().getStringExtra(Constants.BUNDLE_KEY_SHOP_NO);
			mTxtTitle.setText("용인아이 NFC 태그 생성");
			mTxtContents.setText("NFC 태그를 단말기 뒤에 찍어주세요.");
			return;
		}

		Alert.toastShort(this, "샵 정보가 올바르지 않습니다.");
	}

	private void initNFC()
	{
		mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
		mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP), 0);
		IntentFilter discovery = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
		IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
		IntentFilter techDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);

		mWriteTagFilters = new IntentFilter[] { discovery };
	}

	private void configureListener()
	{
		mBtnOK.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				finish();
			}
		});

		// mBtnClose.setOnClickListener(new OnClickListener()
		// {
		// @Override
		// public void onClick(View v)
		// {
		//
		// }
		// });
	}

	@Override
	protected void onResume()
	{
		super.onResume();

		if(mNfcAdapter != null)
		{
			if(!mNfcAdapter.isEnabled())
			{
				Alert dialog = new Alert();
				dialog.showAlert(mContext, "NFC 태그 기능이 비활성화 되어있습니다. 설정하시겠습니까?", false, "설정", "종료");
				dialog.setOnCloseListener(new OnCloseListener()
				{
					@Override
					public void onClose(DialogInterface dialog, int which)
					{
						switch (which)
						{
							case Alert.BUTTON1:
								Intent setnfc = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
								startActivity(setnfc);
								break;
							case Alert.BUTTON2:
								finish();
								break;
						}
					}
				});
			}
			mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mWriteTagFilters, null);
		}
		else
		{
			Alert dialog = new Alert();
			dialog.showAlert(mContext, "이 단말기는 NFC 생성 기능이 없습니다. 앱을 종료합니다.");
			dialog.setOnCloseListener(new OnCloseListener()
			{
				@Override
				public void onClose(DialogInterface dialog, int which)
				{
					finish();
				}
			});
		}
	}

	@Override
	protected void onPause()
	{
		super.onPause();

		if(mNfcAdapter != null)
			mNfcAdapter.disableForegroundDispatch(this);
	}

	@Override
	protected void onNewIntent(Intent intent)
	{
		super.onNewIntent(intent);

		if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()))
		{
			Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
			if(supportedTechs(detectedTag.getTechList()))
			{
				WriteResponse wr = null;
				if(!writableTag(detectedTag))
				{
//					mTxtContents.setText("태그 생성이 불가능합니다. 다른 NFC 태그를 이용해 주세요.");
					
					String mess = "";

					NdefFormatable format = NdefFormatable.get(detectedTag);
					if(format != null)
					{
						try
						{
							format.connect();
							format.format(getTagAsNdef());
							mess = "Formatted tag and wrote message";
							wr = new WriteResponse(1, mess);
						}
						catch (IOException e)
						{
							mess = "Failed to format tag.";
							wr = new WriteResponse(0, mess);
						}
						catch (Exception e)
						{
							e.printStackTrace();
							mess = "Failed to write tag";
							wr = new WriteResponse(0, mess);
						}
					}
					else
					{
						mess = "Tag doesn't support NDEF.";
						wr = new WriteResponse(0, mess);
					}
				}
				else
				{
					wr = writeTag(getTagAsNdef(), detectedTag);

					// WriteResponse wr = writeTag(getTagAsNdef(), detectedTag);
					String message = (wr.getStatus() == 1 ? "Success: " : "Failed: ") + wr.getMessage();
					LogUtil.e(TAG, message);
					if(wr.getStatus() == 1)
					{
						mTxtContents.setText("태그 생성이 완료되었습니다.");
						mBtnOK.setVisibility(View.VISIBLE);
					}
					else
					{
						// Alert dialog = new Alert();
						// dialog.showAlert(mContext, "태그 생성에 실패했습니다. 다시 시도해 주세요.");
						// dialog.setOnCloseListener(new OnCloseListener()
						// {
						// @Override
						// public void onClose(DialogInterface dialog, int which)
						// {
						// finish();
						// }
						// });
						mTxtContents.setText("태그 생성에 실패했습니다. 다시 시도해 주세요.");
					}
				}
//				else
//				{
//					// Alert dialog = new Alert();
//					// dialog.showAlert(mContext, "태그 생성이 불가능합니다. 다른 NFC 태그를 이용해 주세요.");
//					// dialog.setOnCloseListener(new OnCloseListener()
//					// {
//					// @Override
//					// public void onClose(DialogInterface dialog, int which)
//					// {
//					// finish();
//					// }
//					// });
//					mTxtContents.setText("태그 생성이 불가능합니다. 다른 NFC 태그를 이용해 주세요.");
//				}
			}
			else
			{
				// Alert dialog = new Alert();
				// dialog.showAlert(mContext, "지원되지 않는 태그입니다. 다른 NFC 태그를 이용해 주세요.");
				// dialog.setOnCloseListener(new OnCloseListener()
				// {
				// @Override
				// public void onClose(DialogInterface dialog, int which)
				// {
				// finish();
				// }
				// });
				mTxtContents.setText("지원되지 않는 태그입니다. 다른 NFC 태그를 이용해 주세요.");
			}
		}
	}

	public WriteResponse writeTag(NdefMessage message, Tag tag)
	{
		int size = message.toByteArray().length;
		String mess = "";

		try
		{
			Ndef ndef = Ndef.get(tag);
			if(ndef != null)
			{
				ndef.connect();

				if(!ndef.isWritable())
				{
					return new WriteResponse(0, "Tag is read-only");
				}
				if(ndef.getMaxSize() < size)
				{
					mess = "Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size + " bytes.";
					return new WriteResponse(0, mess);
				}

				ndef.writeNdefMessage(message);
				if(mWriteProtect)
					ndef.makeReadOnly();

				NdefRecord[] record = message.getRecords();
				for (int i = 0; i < record.length; i++)
				{
					LogUtil.e("record[" + i + "] : " + record[i]);
					LogUtil.e("record[" + i + "].getTnf : " + record[i].getTnf());
					LogUtil.e("record[" + i + "].getId : " + new String(record[i].getId(), CHART_SET));
					LogUtil.e("record[" + i + "].getType : " + new String(record[i].getType(), CHART_SET));
					LogUtil.e("record[" + i + "].getPayload : " + new String(record[i].getPayload(), CHART_SET));
				}

				mess = "Wrote message to pre-formatted tag.";

				return new WriteResponse(1, mess);
			}
			else
			{
				NdefFormatable format = NdefFormatable.get(tag);
				if(format != null)
				{
					try
					{
						format.connect();
						format.format(message);
						mess = "Formatted tag and wrote message";
						return new WriteResponse(1, mess);
					}
					catch (IOException e)
					{
						mess = "Failed to format tag.";
						return new WriteResponse(0, mess);
					}
				}
				else
				{
					mess = "Tag doesn't support NDEF.";
					return new WriteResponse(0, mess);
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
			mess = "Failed to write tag";
			return new WriteResponse(0, mess);
		}
	}

	private class WriteResponse
	{
		int		status;
		String	message;

		WriteResponse(int Status, String Message)
		{
			this.status = Status;
			this.message = Message;
		}

		public int getStatus()
		{
			return status;
		}

		public String getMessage()
		{
			return message;
		}
	}

	public static boolean supportedTechs(String[] techs)
	{
		boolean ultralight = false;
		boolean nfcA = false;
		boolean ndef = false;
		for (String tech : techs)
		{
			if(tech.equals("android.nfc.tech.MifareUltralight"))
			{
				ultralight = true;
				LogUtil.e("##NFC : ultralight");
			}
			else if(tech.equals("android.nfc.tech.NfcA"))
			{
				nfcA = true;
				LogUtil.e("##NFC : nfcA");
			}
			else if(tech.equals("android.nfc.tech.Ndef") || tech.equals("android.nfc.tech.NdefFormatable"))
			{
				ndef = true;
				LogUtil.e("##NFC : ndef, formatable? : " + tech.equals("android.nfc.tech.NdefFormatable"));

			}
		}
		// if(ultralight && nfcA && ndef)
		if(ultralight || nfcA || ndef)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	private boolean writableTag(Tag tag)
	{
		try
		{
			Ndef ndef = Ndef.get(tag);
			if(ndef != null)
			{
				ndef.connect();
				if(!ndef.isWritable())
				{
					LogUtil.e(TAG, "Tag is read-only.");
					Toast.makeText(mContext, "Tag is read-only.", Toast.LENGTH_SHORT).show();
					ndef.close();
					return false;
				}
				ndef.close();
				return true;
			}
		}
		catch (Exception e)
		{
			LogUtil.e(TAG, "Failed to read tag");
			Toast.makeText(mContext, "Failed to read tag", Toast.LENGTH_SHORT).show();
		}

		return false;
	}

	private NdefMessage getTagAsNdef()
	{
		NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "application/com.juseum.eatnplay2".getBytes(CHART_SET), String.valueOf(mShopNo).getBytes(CHART_SET), new byte[0]);
		NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, "http://www.appg.co.kr".getBytes(CHART_SET), new byte[0], "http://www.appg.co.kr".getBytes(CHART_SET));
		// NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, "http://www.appg.co.kr".getBytes(CHART_SET), new byte[0], new byte[0]);

		// NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "application/com.juseum.eatnplay2".getBytes(CHART_SET), new byte[0], String.valueOf(mShopNo).getBytes(CHART_SET));
		// NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, "http://www.appg.co.kr".getBytes(CHART_SET), new byte[0], "http://www.appg.co.kr".getBytes(CHART_SET));
		// // NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, "http://www.appg.co.kr".getBytes(CHART_SET), new byte[0], new byte[0]);

		return new NdefMessage(new NdefRecord[] { mimeRecord, uriRecord });
	}
}